#ifndef _MSSQL_H_
#define _MSSQL_H_

#define DBNTWIN32

#include <winsock2.h>
#include <windows.h>

#include <utillib/memory/memory.h>
#include <databaselib/io/datatype.h>
#include <utillib/stl/QueueList.h>
#define	TRY_DB_RECONNECTION			10
#define	SLEEP_TIME								10
#define	VALUE_SIZE								1024
#define	MAX_FETCH_CLOUMN				1024
#define	MAX_FETCH_BUFFER					8192

#include <time.h>
#include <databaselib/io/sqlfront.h> 
#include <databaselib/io/sqldb.h> 
#include <utillib/util/Synchronized.h>
#include <databaselib/io/Database.h>

#pragma warning ( disable: 4786 )

#include <map>
#include <deque>
#include <functional>

#ifdef _DEBUG
#pragma comment ( lib, "DataBaseD.lib" )
#else
#pragma comment ( lib, "DataBase.lib" )
#endif

#pragma comment ( lib, "ntwdblib.lib" )

namespace databaselib
{
	namespace io
	{
		class AgentMSSQL;
		class MSSQL : public Database
		{
		public:
			MSSQL( AgentMSSQL *parentDB );
			virtual ~MSSQL();

			virtual bool connect();
			virtual bool release();

			virtual bool executeSQL(const char *query );
			virtual bool fetch();

			bool isConnect();

			bool rpcinit( const char *rpcName );
			bool addParam( const char *name, BYTE valueType , bool returnValue = false , void *data = NULL , int dataSize = -1, int maxSize = -1 );
			bool addParam( const char *name, char *data, bool returnValue = false  );
			bool addParam( const char *name, short *data, bool returnValue = false  );
			bool addParam( const char *name, int *data, bool returnValue = false  );
			bool addParam( const char *name, float *data, bool returnValue = false  );
			bool addParam( const char *name, BYTE *data, bool returnValue = false  );
			bool addParam( const char *name, WORD *data, bool returnValue = false  );
			bool addParam( const char *name, DWORD *data, bool returnValue = false  );
			
			bool executeRPC();
		private:
			bool _executeSQL(const char *query );
			bool _executeRPC();
			bool getResultSet();
			void endFetch();

			template < class _Ty >
			bool getData( _Ty &out )
			{
				if ( m_isFetch )
				{
					m_columnNo++;
					LPCBYTE data = NULL;
					if ( m_isRPCExecute ) data = dbretdata( m_DBProcess, m_columnNo );
					else data = dbdata( m_DBProcess, m_columnNo );
					if ( data )
					{
						out = *( _Ty * )data;
						return ( true ) ;
					}
				}
				return ( false );
			}
		public:
			virtual MSSQL& operator >> ( char &out )
			{
				getData( out );
				return ( *this );
			};
			virtual MSSQL& operator >> ( bool &out )
			{
				getData( out );
				return ( *this );
			};
			virtual MSSQL& operator >> ( unsigned int &out )
			{
				getData( out );
				return ( *this );
			};
			virtual MSSQL& operator >> ( int &out )
			{
				getData( out );
				return ( *this );
			};
			virtual MSSQL& operator >> ( unsigned long &out )
			{
				getData( out );
				return ( *this );
			};
			virtual MSSQL& operator >> ( float &out )
			{
				getData( out );
				return ( *this );
			};
			virtual MSSQL& operator >> ( short &out )
			{
				getData( out );
				return ( *this );
			};
			virtual MSSQL& operator >> ( unsigned short &out )
			{
				getData( out );
				return ( *this );
			};
			virtual MSSQL& operator >> ( unsigned char &out )
			{
				getData( out );
				return ( *this );
			};
			MSSQL& operator >> ( char *out );
			MSSQL& operator >> ( __int64 &out );
			MSSQL& operator >> ( unsigned __int64 &out );
			MSSQL& operator >> ( struct tm &out );
			MSSQL& operator >> ( SmallDate &out );

		private:
			int m_columnNo;
			PDBPROCESS m_DBProcess;
			bool m_isFetch;
			bool m_isExecute;
			bool m_isRPCExecute;

			AgentMSSQL *m_parentDB;
		};
		class AgentMSSQL : public AgentDB
		{
		public:

			AgentMSSQL();
			virtual ~AgentMSSQL();

			static void initializeDB();

		public:
			bool initializeDataBaseEnv( char *dataBaseIP, char *defaultDB, char *userid, char *password );
			bool releaseDataBaseEnv();

			virtual Database *getNewDBInstance();

			char *getIP(){ return ( m_serverAddress ); };
			char *getCatalog(){ return ( m_catalog ); };
			char *getID(){ return ( m_userid ); };
			char *getPassword(){ return ( m_password ); };
		protected:

			char *m_password;
			char *m_userid;
			char *m_serverAddress;
			char *m_catalog;
		};
	};
};

#endif